package values

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strings"
	"sync"
	"time"
	"unsafe"
)

// ToSliceMap 转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回空的 []map[K]V 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
//   - 转换时切片中的map元素如为nil将会忽略(跳过)
func ToSliceMap[K TypeBase, V TypeBase](v any) []map[K]V {
	val, _ := ToSliceMapE[K, V](v)
	return val
}

// ToSliceMapD 转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回defaultVal指定的默认值
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
//   - 转换时切片中的map元素如为nil将会忽略(跳过)
func ToSliceMapD[K TypeBase, V TypeBase](v any, defaultVal []map[K]V) []map[K]V {
	if v == nil {
		return defaultVal
	}
	if val, err := ToSliceMapE[K, V](v); err == nil {
		return val
	}
	return defaultVal
}

// ToSliceMapE 转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回空的 []map[K]V 切片和错误信息
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
//   - 转换时切片中的map元素如为nil将会忽略(跳过)
func ToSliceMapE[K TypeBase, V TypeBase](v any) ([]map[K]V, error) {
	return _toSliceMapE[K, V](UnderefVal(v))
}

// _toSliceMapE 转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回空的 []map[K]V 切片和错误信息
//   - 待转换目标为已经UnderefVal处理的参数
func _toSliceMapE[K TypeBase, V TypeBase](v any) ([]map[K]V, error) {
	toVal := []map[K]V{}
	if v == nil {
		return toVal, errors.New("ToSliceMapE: nil pointer not support")
	}
	// 先通过断言判断待转换值是否为 []any / []map[K]V / []map[K]any / []map[any]any / JsonString 类型
	switch vs := v.(type) {
	case []any:
		for i := range vs {
			vs[i] = UnderefVal(vs[i])
			if vs[i] == nil {
				continue
			}
			if val, err := _toMapAsE[K, V](vs[i]); err == nil {
				toVal = append(toVal, val)
			} else {
				return toVal, err
			}
		}
		return toVal, nil
	case []map[K]V:
		return _toSliceMapAppend(vs)
	case []map[K]any:
		return _toSliceMapAnyV[K, V](vs)
	case []map[any]any:
		return _toSliceMapAnyKV[K, V](vs)
	case []*map[K]V:
		for i := range vs {
			if vs[i] == nil {
				continue
			}
			toVal = append(toVal, *vs[i])
		}
		return toVal, nil
	case []*map[K]any:
		var toAny []map[K]any
		for i := range vs {
			if vs[i] == nil {
				continue
			}
			toAny = append(toAny, *vs[i])
		}
		return _toSliceMapAnyV[K, V](toAny)
	case []*map[any]any:
		var toAny []map[any]any
		for i := range vs {
			if vs[i] == nil {
				continue
			}
			toAny = append(toAny, *vs[i])
		}
		return _toSliceMapAnyKV[K, V](toAny)

	case []byte:
		if json.Valid(vs) {
			var toAny []map[K]any
			if err := json.Unmarshal(vs, &toAny); err == nil {
				return _toSliceMapAnyV[K, V](toAny)
			} else {
				return toVal, fmt.Errorf("ToSliceMapE: []byte to []map[K]V type, failed unmarshal: %s", err.Error())
			}
		}
		return toVal, errors.New("ToSliceMapE: []byte to []map[K]V type not support")
	case string:
		vsBytes := StringToBytes(vs)
		if vs != "" && strings.HasPrefix(vs, "[") && strings.HasSuffix(vs, "]") && json.Valid(vsBytes) {
			var toAny []map[K]any
			if err := json.Unmarshal(vsBytes, &toAny); err == nil {
				return _toSliceMapAnyV[K, V](toAny)
			} else {
				return toVal, fmt.Errorf("ToSliceMapE: string to []map[K]V type, failed unmarshal: %s", err.Error())
			}
		}
		return toVal, errors.New("ToSliceMapE: string to []map[K]V type not support")
	case bool,
		int, int8, int16, int32, int64,
		uint, uint8, uint16, uint32, uint64, uintptr,
		float32, float64,
		complex64, complex128,
		time.Time, time.Duration, time.Location, time.Month, time.Weekday, time.Ticker, time.Timer,
		struct{}, chan any, func(), unsafe.Pointer,
		bytes.Buffer, strings.Builder,
		reflect.Type, reflect.Value, reflect.Kind,
		sync.Mutex, sync.RWMutex, sync.Cond, sync.Once, sync.Pool, sync.WaitGroup, sync.Locker,
		error,
		json.Number:
		// 如果待转换值是Golang 常用的基本类型, 则直接返回错误信息
		return toVal, errors.New("ToSliceMapE: basicType to []map[K]V type not support")
	}

	// v 值已经通过UnderefVal检查, 这里直接使用反射获取类型即可
	switch reflect.TypeOf(v).Kind() {
	case reflect.Slice:
		// 通过断言判断待转换值是否为 []map[X]X 类型
		if toVal, err, next := _toSliceMapWith[K, V](v); !next {
			return toVal, err
		}
	case reflect.Array:
		// 通过反射, 尝试将判断待转换值是否为 []map[X]X 类型
		reVal := reflect.ValueOf(v)
		lenSlice := reVal.Len()
		toSlice := make([]map[K]V, 0, lenSlice)
		// 遍历切片, 尝试将元素转换为 map[K]V 类型
		for i := range lenSlice {
			itemVal := reVal.Index(i)
			if itemVal.Kind() != reflect.Map {
				return toVal, fmt.Errorf("ToSliceMapE: type %T to type %T not support", v, toVal)
			}
			itemAny := itemVal.Interface()
			if itemAny == nil {
				// 跳过 nil 元素
				continue
			}
			if val, err := ToMapAsE[K, V](itemAny); err == nil {
				toSlice = append(toSlice, val)
			} else {
				return toVal, err
			}
		}
		return toSlice, nil
	}
	return toVal, fmt.Errorf("ToSliceMapE: type %T to type %T not support", v, toVal)
}

func _toSliceMapAppend[K TypeBase, V TypeBase](vs []map[K]V) ([]map[K]V, error) {
	if vs == nil {
		return []map[K]V{}, errors.New("ToSliceMapE: nil pointer not support")
	}
	if len(vs) == 0 {
		return []map[K]V{}, nil
	}
	toVal := make([]map[K]V, len(vs))
	copy(toVal, vs)
	return toVal, nil
}
func _toSliceMapAnyV[K TypeBase, V TypeBase](vs []map[K]any) ([]map[K]V, error) {
	if vs == nil {
		return []map[K]V{}, errors.New("ToSliceMapE: nil pointer not support")
	}
	if len(vs) == 0 {
		return []map[K]V{}, nil
	}
	toMap := make([]map[K]V, len(vs))

	for key, item := range vs {
		if item == nil {
			return []map[K]V{}, errors.New("ToSliceMapE: nil pointer not support")
		}
		if len(item) == 0 {
			toMap[key] = map[K]V{}
			continue
		}
		toVal := make(map[K]V, len(item))
		for k, v := range item {
			v = UnderefVal(v)
			if v == nil {
				return []map[K]V{}, errors.New("ToSliceMapE: nil pointer not support")
			}
			if val, ok := v.(V); ok {
				toVal[k] = val
				continue
			} else if val, err := _toBaseE[V](v); err == nil {
				toVal[k] = val
			} else {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: %T to type %T,error: %s", v, val, err.Error())
			}
		}
		toMap[key] = toVal
	}
	return toMap, nil
}
func _toSliceMapAnyKV[K TypeBase, V TypeBase](vs []map[any]any) ([]map[K]V, error) {
	if vs == nil {
		return []map[K]V{}, errors.New("ToSliceMapE: nil pointer not support")
	}
	if len(vs) == 0 {
		return []map[K]V{}, nil
	}
	toVal := make([]map[K]V, len(vs))
	var (
		toK K
		toV V
	)
	for i, maps := range vs {
		if maps == nil {
			return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps is nil, nil pointer not support", i)
		}
		if len(maps) == 0 {
			toVal[i] = map[K]V{}
			continue
		}
		toMap := make(map[K]V, len(maps))
		for key, item := range maps {
			key = UnderefVal(key)
			item = UnderefVal(item)
			if key == nil || item == nil {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps key or val is nil, nil pointer not support", i)
			}
			if val, ok := key.(K); ok {
				toK = val
			} else if val, err := _toBaseE[K](key); err == nil {
				toK = val
			} else {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps key[%#v] to type of %T, error:%s", i, key, toK, err.Error())
			}
			if val, ok := item.(V); ok {
				toV = val
			} else if val, err := _toBaseE[V](item); err == nil {
				toV = val
			} else {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps val[%#v] to type of %T,, error:%s", i, item, toV, err.Error())
			}
			toMap[toK] = toV
		}
		toVal[i] = toMap
	}
	return toVal, nil
}
func _toSliceMapWith[K TypeBase, V TypeBase](v any) ([]map[K]V, error, bool) {
	// 通过断言判断待转换值是否为 []map[X]X 类型
	if toVal, err, next := _toSliceMapWithKey[K, V, string](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, int](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, uint](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, int64](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, uint64](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, int32](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, uint32](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, int16](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, uint16](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, int8](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, uint8](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, float32](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, float64](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, float64](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, time.Time](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, time.Duration](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, time.Month](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, time.Weekday](v); !next {
		return toVal, err, false
	}
	if toVal, err, next := _toSliceMapWithKey[K, V, bool](v); !next {
		return toVal, err, false
	}
	return []map[K]V{}, nil, true // Next "true" To continue
}
func _toSliceMapWithKey[K TypeBase, V TypeBase, Key TypeBase](v any) ([]map[K]V, error, bool) {
	switch vs := v.(type) {
	default:
		return []map[K]V{}, nil, true // Next "true" To continue
	case []map[Key]V:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]any:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]string:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]bool:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]int:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]int8:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]int16:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]int32:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]int64:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]uint:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]uint8:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]uint16:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]uint32:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]uint64:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]float32:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]float64:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]time.Time:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]time.Duration:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]time.Weekday:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]time.Month:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]json.Number:
		return _toSliceMapWithLoop[K, V](vs)
	case []map[Key]error:
		return _toSliceMapWithLoop[K, V](vs)
	case []*map[Key]V:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]any:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]string:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]bool:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]int:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]int8:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]int16:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]int32:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]int64:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]uint:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]uint8:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]uint16:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]uint32:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]uint64:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]float32:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]float64:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]time.Time:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]time.Duration:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]time.Weekday:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]time.Month:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]json.Number:
		return _toSliceMapWithLoopPtr[K, V](vs)
	case []*map[Key]error:
		return _toSliceMapWithLoopPtr[K, V](vs)
	}
}
func _toSliceMapWithLoop[K TypeBase, V TypeBase, vsK TypeBase, vsV any](vs []map[vsK]vsV) ([]map[K]V, error, bool) {
	if vs == nil {
		return []map[K]V{}, errors.New("ToMapSliceE: nil pointer not support"), false // Next "false" To Break
	}
	if len(vs) == 0 {
		return []map[K]V{}, nil, false // Next "false" To Break
	}
	toVal := make([]map[K]V, len(vs))
	var (
		toK K
		toV V
	)
	for i, maps := range vs {
		if maps == nil {
			return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps is nil, nil pointer not support", i), false
		}
		if len(maps) == 0 {
			toVal[i] = map[K]V{}
			continue
		}
		toMap := make(map[K]V, len(maps))
		for key, item := range maps {
			anyKey := UnderefVal(key)
			if val, ok := anyKey.(K); ok {
				toK = val
			} else if val, err := _toBaseE[K](anyKey); err == nil {
				toK = val
			} else {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps key[%#v] to type of %T, error:%s", i, key, toK, err.Error()), false
			}
			anyItem := UnderefVal(item)
			if anyItem == nil {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps key or val is nil, nil pointer not support", i), false
			}
			if val, ok := anyItem.(V); ok {
				toV = val
			} else if val, err := _toBaseE[V](anyItem); err == nil {
				toV = val
			} else {
				return []map[K]V{}, fmt.Errorf("ToSliceMapE: slice index[%d] maps val[%#v] to type of %T,, error:%s", i, item, toV, err.Error()), false
			}
			toMap[toK] = toV
		}
		toVal[i] = toMap
	}
	return toVal, nil, false
}
func _toSliceMapWithLoopPtr[K TypeBase, V TypeBase, vsK TypeBase, vsV any](vs []*map[vsK]vsV) ([]map[K]V, error, bool) {
	if vs == nil {
		return []map[K]V{}, errors.New("ToMapSliceE: nil pointer not support"), false // Next "false" To Break
	}
	if len(vs) == 0 {
		return []map[K]V{}, nil, false // Next "false" To Break
	}

	vsVal := make([]map[vsK]vsV, 0, len(vs))
	for _, maps := range vs {
		if maps == nil {
			continue
		}
		vsVal = append(vsVal, *maps)
	}
	return _toSliceMapWithLoop[K, V](vsVal)
}
